import { ColumnBatchCreator, ColumnCreator } from "@/views/components/ColumnEditor";
// import { ActionColumnBatchCreator, ActionColumnCreator } from "@/views/components/ActionElementEditor";
import { AppConfiguration, MicroConfiguration, SeedConfiguration } from "@/views/dev-types";
import { TreeInstance } from "element-plus";
import { computed, ComputedRef, ref } from "vue";
import type Node from 'element-plus/es/components/tree/src/model/node'
import { open } from "@/components/Popup";
import StatCreator from "@/views/components/StatEditor/src/StatCreator.vue";
import { ActionCreator } from "@/views/components/ActionEditor";
import { HomeCreator } from "@/views/components/HomeEditor";
import { SeedCreator } from "@/views/components/SeedEditor";
import { MicroCreator } from "@/views/components/MicroEditor";
import { RelationCreator } from "@/views/components/RelationEditor";
import { StatBatchCreator } from "@/views/components/StatEditor";

export type ActiveType = 'property'|'component'|'layout'
export type CreateType = 
  'micro'|'action'|'action-column'|'action-stat'|'home'|'seed'|
  'seed-action'|'seed-action-column'|'seed-action-stat'|'seed-column'|'seed-stat'|
  'seed-has-one'|'seed-belongs-to'|'seed-has-many'|'seed-habtm'
export type DevType = 'applist'|'app'|'login'|'default-home'|'root'|'error'|'redirect'|CreateType

export const unitKey = Symbol('unit')

export interface TreeNode {
  id?: string
  label?: string
  type?: CreateType
  seedName?: string
  actionName?: string
  statName?: string
  columnName?: string
  homeName?: string
  cross?: string
  children?: TreeNode[]
}

export const currentApp = ref<AppConfiguration>()
export const currentMicro = ref<string>()
export const treeRef = ref<TreeInstance>()
export const active = ref<ActiveType>()
export const breadcrumbs = ref<{type: DevType, label: string | ComputedRef<string>, node?: Node}[]>([])

export function getAppId(app: AppConfiguration) {
  if(!app) return void 0

  return `${app?.owner ? app?.owner + '.' : ''}${app?.name}`
}

export function toTreeData(micro: MicroConfiguration): TreeNode[] {
  const ret = []
  if(!micro) return ret

  const actions = micro.actions
  if(actions) {
    for(const actionName in actions) {
      const action = actions[actionName]

      const children = []
      const columns = action.columns
      if(columns && Object.keys(columns).length > 0) {
        for(const columnName in columns) {
          const column = columns[columnName]
          children.push({
            id: `${actionName}-${columnName}`,
            label: column.label,
            type: 'action-column',
            icon: 'ic:baseline-view-column',
            color: '#67C23A',
            actionName,
            columnName
          })
        }
      }

      const stats = action.stats
      if(stats && Object.keys(stats).length > 0) {
        for(const statName in stats) {
          const stat = stats[statName]
          children.push({
            id: `${actionName}-${statName}`,
            label: stat.label,
            type: 'action-stat',
            icon: 'nimbus:stats',
            color: '#E6A23C',
            actionName,
            statName
          })
        }
      }

      ret.push({
        id: actionName,
        label: action.label,
        type: 'action',
        icon: 'fluent-mdl2:set-action',
        color: '#409EFF',
        actionName,
        children
      })
    }
  }

  const homes = micro.homes
  if(homes) {
    for(const homeName in homes) {
      const home = homes[homeName]
      ret.push({id: homeName, label: home.label, type: 'home', icon: 'ic:outline-home', color: '#909399', homeName})
    }
  }

  const seeds = micro.seeds
  if(!seeds) return ret
  
  for(const seedName in seeds) {
    const seed = seeds[seedName]
    
    const children = []
    const actions = seed.actions
    if(actions && Object.keys(actions).length > 0) {
      for(const actionName in actions) {
        const action = actions[actionName]

        const subChidren = []
        const columns = action.columns
        if(columns && Object.keys(columns).length > 0) {
          for(const columnName in columns) {
            const column = columns[columnName]
            subChidren.push({
              id: `${seedName}-${actionName}-${columnName}`,
              label: column.label,
              type: 'seed-action-column',
              icon: 'ic:baseline-view-column',
              color: '#67C23A',
              seedName,
              actionName,
              columnName
            })
          }
        }

        const stats = action.stats
        if(stats && Object.keys(stats).length > 0) {
          for(const statName in stats) {
            const stat = stats[statName]
            subChidren.push({
              id: `${seedName}-${actionName}-${statName}`,
              label: stat.label,
              type: 'seed-action-stat',
              icon: 'nimbus:stats',
              color: '#E6A23C',
              seedName,
              actionName,
              statName
            })
          }
        }

        children.push({
          id: `${seedName}-${actionName}`,
          label: action.label,
          type: 'seed-action',
          icon: 'fluent-mdl2:set-action',
          color: '#409EFF',
          seedName,
          actionName,
          children: subChidren
        })
      }
    }

    const columns = seed.columns
    if(columns && Object.keys(columns).length > 0) {
      for(const columnName in columns) {
        const column = columns[columnName]
        children.push({
          id: `${seedName}-${columnName}`,
          label: column.label,
          type: 'seed-column',
          icon: 'ic:baseline-view-column',
          color: '#67C23A',
          seedName,
          columnName
        })
      }
    }

    const stats = seed.stats
    if(stats && Object.keys(stats).length > 0) {
      for(const statName in stats) {
        const stat = stats[statName]
        children.push({
          id: `${seedName}-${statName}`,
          label: stat.label,
          type: 'seed-stat',
          icon: 'nimbus:stats',
          color: '#E6A23C',
          seedName,
          statName
        })
      }
    }

    const hasOne = seed.hasOne
    if(hasOne && Object.keys(hasOne).length > 0) {
      for(const cross in hasOne) {
        const relation = hasOne[cross]
        children.push({
          id: `${seedName}-${cross}`,
          label: relation.label,
          type: 'seed-has-one',
          icon: 'icon-park:one-to-one',
          seedName,
          cross
        })
      }
    }

    const belongsTo = seed.belongsTo
    if(belongsTo && Object.keys(belongsTo).length > 0) {
      for(const cross in belongsTo) {
        const relation = belongsTo[cross]
        children.push({
          id: `${seedName}-${cross}`,
          label: relation.label,
          type: 'seed-belongs-to',
          icon: 'mdi:relation-many-to-one',
          seedName,
          cross
        })
      }
    }

    const hasMany = seed.hasMany
    if(hasMany && Object.keys(hasMany).length > 0) {
      for(const cross in hasMany) {
        const relation = hasMany[cross]
        children.push({
          id: `${seedName}-${cross}`,
          label: relation.label,
          type: 'seed-has-many',
          icon: 'icon-park:one-to-many',
          seedName,
          cross
        })
      }
    }

    const habtm = seed.habtm
    if(habtm && Object.keys(habtm).length > 0) {
      for(const cross in habtm) {
        const relation = habtm[cross]
        children.push({
          id: `${seedName}-${cross}`, 
          label: relation.label,
          type: 'seed-habtm',
          icon: 'icon-park:many-to-many',
          seedName,
          cross
        })
      }
    }

    ret.push({
      id: seedName,
      label: seed.label,
      type: 'seed',
      icon: 'streamline-ultimate-color:module-hands-puzzle',
      color: '#F56C6C',
      seedName,
      children
    })
  }

  return ret
}

export function setBreadcrumbs(type: DevType, node?: Node, isTreeClick?: boolean) {
  if(!type) {
    treeRef.value?.setCurrentKey()
    breadcrumbs.value = []
    return
  }

  if(['applist','app','micro','login','default-home','root','error','redirect'].includes(type)) {
    treeRef.value?.setCurrentKey()
    switch(type) {
      case 'applist':
        breadcrumbs.value = [{type, label: '我的应用'}]
        break
      case 'app':
        breadcrumbs.value = [{type, label: computed(() => currentApp.value.label)}]
        currentMicro.value = void 0
        break
      case 'micro':
        breadcrumbs.value = [
          {type: 'app', label: currentApp.value.label},
          {type, label: computed(() => currentApp.value.micros[currentMicro.value].label)}
        ]
        break
      case 'login':
        breadcrumbs.value = [{type: 'app', label: currentApp.value.label}, {type, label: '登录页面'}]
        break
      case 'default-home':
        breadcrumbs.value = [{type: 'app', label: currentApp.value.label}, {type, label: '默认首页'}]
        break
      case 'root':
        breadcrumbs.value = [{type: 'app', label: currentApp.value.label}, {type, label: '母页面'}]
        break
      default: // 'error'|'redirect'
        
    }
  } else {
    if(!isTreeClick) treeRef.value?.setCurrentKey(node.data.id)
    switch(type) {
      case 'action':
        breadcrumbs.value = getActionBreadcrumbs(node)
        break
      case 'action-column':
        breadcrumbs.value = getActionColumnBreadcrumbs(node)
        break
      case 'action-stat':
        breadcrumbs.value = getActionStatBreadcrumbs(node)
        break
      case 'home':
        breadcrumbs.value = getHomeBreadcrumbs(node)
        break
      case 'seed':
        breadcrumbs.value = getSeedBreadcrumbs(node)
        break
      case 'seed-action':
        breadcrumbs.value = getSeedActionBreadcrumbs(node)
        break
      case 'seed-action-column':
        breadcrumbs.value = getSeedActionColumnBreadcrumbs(node)
        break
      case 'seed-action-stat':
        breadcrumbs.value = getSeedActionStatBreadcrumbs(node)
        break
      case 'seed-column':
        breadcrumbs.value = getSeedColumnBreadcrumbs(node)
        break
      case 'seed-stat':
        breadcrumbs.value = getSeedStatBreadcrumbs(node)
        break
      case 'seed-has-one':
        breadcrumbs.value = getSeedHasOneBreadcrumbs(node)
        break
      case 'seed-belongs-to':
        breadcrumbs.value = getSeedBelongsToBreadcrumbs(node)
        break
      case 'seed-has-many':
        breadcrumbs.value = getSeedHasManyBreadcrumbs(node)
        break
      case 'seed-habtm':
        breadcrumbs.value = getSeedHabtmBreadcrumbs(node)
        break
    }
  }
}

function getMicroBreadcrumbs() {
  const ret: {type: DevType, label: string | ComputedRef<string>, node?: Node}[] = [{type: 'app', label: computed(() => currentApp.value.label)}]
  if(currentMicro.value) {
    ret.push({type: 'micro', label: computed(() => currentApp.value.micros[currentMicro.value].label)})
  }

  return ret
}

function getActionBreadcrumbs(node: Node) {
  const ret = getMicroBreadcrumbs()
  ret.push({type: 'action', label: computed(() => node.label), node})

  return ret
}

function getActionColumnBreadcrumbs(node: Node) {
  const ret = getActionBreadcrumbs(node.parent)
  ret.push({type: 'action-column', label: computed(() => node.label), node})

  return ret
}

function getActionStatBreadcrumbs(node: Node) {
  const ret = getActionBreadcrumbs(node.parent)
  ret.push({type: 'action-stat', label: computed(() => node.label), node})

  return ret
}

function getHomeBreadcrumbs(node: Node) {
  const ret = getMicroBreadcrumbs()
  ret.push({type: 'home', label: computed(() => node.label), node})

  return ret
}

function getSeedBreadcrumbs(node: Node) {
  const ret = getMicroBreadcrumbs()
  ret.push({type: 'seed', label: computed(() => node.label), node})

  return ret
}

function getSeedActionBreadcrumbs(node: Node) {
  const ret = getSeedBreadcrumbs(node.parent)
  ret.push({type: 'seed-action', label: computed(() => node.label), node})

  return ret
}

function getSeedActionColumnBreadcrumbs(node: Node) {
  const ret = getSeedActionBreadcrumbs(node.parent)
  ret.push({type: 'seed-action-column', label: computed(() => node.label), node})

  return ret
}

function getSeedActionStatBreadcrumbs(node: Node) {
  const ret = getSeedActionBreadcrumbs(node.parent)
  ret.push({type: 'seed-action-stat', label: computed(() => node.label), node})

  return ret
}

function getSeedColumnBreadcrumbs(node: Node) {
  const ret = getSeedBreadcrumbs(node.parent)
  ret.push({type: 'seed-column', label: computed(() => node.label), node})

  return ret
}

function getSeedStatBreadcrumbs(node: Node) {
  const ret = getSeedBreadcrumbs(node.parent)
  ret.push({type: 'seed-stat', label: computed(() => node.label), node})

  return ret
}

function getSeedHasOneBreadcrumbs(node: Node) {
  const ret = getSeedBreadcrumbs(node.parent)
  ret.push({type: 'seed-has-one', label: computed(() => node.label), node})

  return ret
}

function getSeedBelongsToBreadcrumbs(node: Node) {
  const ret = getSeedBreadcrumbs(node.parent)
  ret.push({type: 'seed-belongs-to', label: computed(() => node.label), node})

  return ret
}

function getSeedHasManyBreadcrumbs(node: Node) {
  const ret = getSeedBreadcrumbs(node.parent)
  ret.push({type: 'seed-has-many', label: computed(() => node.label), node})

  return ret
}

function getSeedHabtmBreadcrumbs(node: Node) {
  const ret = getSeedBreadcrumbs(node.parent)
  ret.push({type: 'seed-habtm', label: computed(() => node.label), node})

  return ret
}

export function getActiveOptions(type: DevType) {
  if(type === 'applist') return []

  if(['action-stat', 'seed-stat', 'seed-action-stat', 'seed-has-one', 'seed-belongs-to', 'seed-has-many', 'seed-habtm'].includes(type)) {
    active.value = 'property'
    return [ { value: 'property', label: '属性', icon: 'hugeicons:property-edit' } ]
  }
  if(['seed-column', 'action-column', 'seed-action-column'].includes(type)) {
    active.value = 'property'
    return [
      { value: 'property', label: '属性', icon: 'hugeicons:property-edit' },
      { value: 'component', label: '组件', icon: 'iconoir:component' }
    ]
  }

  if(['root', 'default-home', 'login'].includes(type)) {
    active.value = 'component'
    return [
      { value: 'component', label: '组件', icon: 'iconoir:component' },
      { value: 'layout', label: '设计', icon: 'mdi:design' }
    ]
  }
  
  active.value = 'property'
  return [
    { value: 'property', label: '属性', icon: 'hugeicons:property-edit' },
    { value: 'component', label: '组件', icon: 'iconoir:component' },
    { value: 'layout', label: '设计', icon: 'mdi:design' }
  ]
}

export function getCreators(type: DevType, data: TreeNode) {
  if(!type) return []

  switch(type) {
    case 'action': return getActionContextItems(data.actionName)
    case 'seed':
      const seedName = data.seedName
      return [
        { label: '创建列', icon: 'carbon:create-link', onClick: () => open({title: '创建列'}, ColumnCreator, {seedName}) },
        { label: '批量创建列', icon: 'lsicon:batch-add-outline', onClick: () => open({title: '批量创建列'}, ColumnBatchCreator, {seedName}) },
        { label: '创建统计', icon: 'gridicons:stats', onClick: () => open({title: '创建统计'}, StatCreator, {seedName}) },
        { label: '批量创建统计', icon: 'lsicon:batch-add-outline', onClick: () => open({title: '批量创建统计'}, StatBatchCreator, {seedName}) },
        { label: '创建功能', icon: 'ix:create-plant', onClick: () => open({title: '创建功能'}, ActionCreator, {seedName}) },
        { label: '一对一', icon: 'icon-park:one-to-one', onClick: () => open({title: '创建一对一'}, RelationCreator, {seedName, type: 'hasOne'}) },
        { label: '多对一', icon: 'mdi:relation-many-to-one', onClick: () => open({title: '创建多对一'}, RelationCreator, {seedName, type: 'belongsTo'}) },
        { label: '一对多', icon: 'icon-park:one-to-many', onClick: () => open({title: '创建一对多'}, RelationCreator, {seedName, type: 'hasMany'}) },
        { label: '多对多', icon: 'icon-park:many-to-many', onClick: () => open({title: '创建多对多'}, RelationCreator, {seedName, type: 'habtm'}) }
      ]
    case 'seed-action': return getSeedActionContextItems(data.seedName, data.actionName)
    case 'app':
      return [
        { label: '功能', icon: 'ix:create-plant', onClick: () => open({title: '创建功能'}, ActionCreator) },
        { label: '首页', icon: 'uil:create-dashboard', onClick: () => open({title: '创建首页'}, HomeCreator) },
        { label: '模块', icon: 'gridicons:create', onClick: () => open({title: '创建模块'}, SeedCreator) },
        { label: '微服务', icon: 'mdi:create-new-folder-outline', onClick: () => open({title: '创建微服务'}, MicroCreator) }
      ]
    case 'micro':
      return [
        { label: '功能', icon: 'ix:create-plant', onClick: () => open({title: '创建功能'}, ActionCreator) },
        { label: '首页', icon: 'uil:create-dashboard', onClick: () => open({title: '创建首页'}, HomeCreator) },
        { label: '模块', icon: 'gridicons:create', onClick: () => open({title: '创建模块'}, SeedCreator) }
      ]
    default: return []
  }
}

function getActionContextItems(actionName: string) {
  const ret = []
  // const action = getAction(actionName)
  // const seedName = action.seedName
  // if(!seedName) return ret

  // const seed = getSeed(action.seedName)
  // if(seed && seed.columns) {
  //   const columnNames = Object.keys(action.columns|| {})
  //   for(const columnName in seed.columns) {
  //     if(columnNames.includes(columnName)) continue

  //     const column = seed.columns[columnName]
  //     const label = `重写【${column.label}】`
  //     ret.push({ label, icon: 'carbon:create-link', onClick: () => open({title: label}, ActionColumnCreator, {actionName, columnName}) })
  //   }
  // }
  // if(ret.length > 0) {
  //   ret.push({
  //     label: '批量重写列',
  //     icon: 'lsicon:batch-add-outline',
  //     onClick: () => open({title: '批量重写列'}, ActionColumnBatchCreator, { actionName })
  //   })
  // }
  
  // ret.push({ label: '创建统计', icon: 'gridicons:stats', onClick: () => open({title: '创建统计'}, StatCreator, {actionName}) })
  // ret.push({ label: '批量创建统计', icon: 'lsicon:batch-add-outline', onClick: () => open({title: '批量创建统计'}, StatBatchCreator, {actionName}) })

  return ret
}

function getSeedActionContextItems(seedName: string, actionName: string) {
  const ret = []
  // const seed = getSeed(seedName)
  // const action = seed.actions[actionName]
  // if(seed.columns) {
  //   const columnNames = Object.keys(action.columns|| {})
  //   for(const columnName in seed.columns) {
  //     if(columnNames.includes(columnName)) continue
      
  //     const column = seed.columns[columnName]
  //     const label = `重写【${column.label}】`
  //     ret.push({ label, icon: 'carbon:create-link', onClick: () => open({title: label}, ActionColumnCreator, {seedName, actionName}) })
  //   }
  // }
  // if(ret.length > 0) {
  //   ret.push({
  //     label: '批量重写列',
  //     icon: 'lsicon:batch-add-outline',
  //     onClick: () => open({title: '批量重写列'}, ActionColumnBatchCreator, { seedName, actionName })
  //   })
  // }
  // ret.push({ label: '创建统计', icon: 'gridicons:stats', onClick: () => open({title: '创建统计'}, StatCreator, {seedName, actionName}) })
  // ret.push({ label: '批量创建统计', icon: 'lsicon:batch-add-outline', onClick: () => open({title: '批量创建统计'}, StatBatchCreator, {seedName, actionName}) })
  return ret
}

export function getSeed(seedName: string) {
  return getSeeds()?.[seedName]
}

export function getSeeds() {
  const microName = currentMicro.value
  return microName ? currentApp.value.micros[microName]?.seeds : currentApp.value.seeds
}

export function getAction(actionName: string) {
  const microName = currentMicro.value
  if(microName) {
    const micro = currentApp.value.micros[microName]
    return micro.actions?.[actionName]
  } else {
    const app = currentApp.value
    return app.actions?.[actionName]
  }
}

export function getDeclareNode(seed: SeedConfiguration, parentValue?: string) {
  const ret = []
  const columns = seed.columns
  for(const columnName in columns) {
    const value = parentValue ? `${parentValue}.${columnName}` : columnName
    ret.push({value, label: columns[columnName].label})
  }

  const hasOne = seed.hasOne
  if(hasOne) {
    for(const cross in hasOne) {
      const value = parentValue ? `${parentValue}.${cross}` : cross
      const item = hasOne[cross]
      ret.push({value, label: item.label, seedName: item.seedName })
    }
  }

  const belongsTo = seed.belongsTo
  if(belongsTo) {
    for(const cross in belongsTo) {
      const value = parentValue ? `${parentValue}.${cross}` : cross
      const item = belongsTo[cross]
      ret.push({value, label: item.label, seedName: item.seedName})
    }
  }

  const hasMany = seed.hasMany
  if(hasMany) {
    for(const cross in hasMany) {
      const value = parentValue ? `${parentValue}.${cross}` : cross
      const item = hasMany[cross]
      console.log('item==', item, seed)
      ret.push({value, label: item.label, seedName: item.seedName})
    }
  }

  const habtm = seed.habtm
  if(habtm) {
    for(const cross in habtm) {
      const value = parentValue ? `${parentValue}.${cross}` : cross
      const item = habtm[cross]
      ret.push({value, label: item.label, seedName: item.seedName})
    }
  }

  return ret
}
